using System;
using System.Messaging;
using NUnit.Framework;
using MessageGateway;
using System.Threading;
using System.Xml;

namespace MessageGatewayMSMQ
{

    [TestFixture]
	public class TestMessageGatewayMSMQ
	{
        IMessageGatewayFactory factory;
        int receivedCount1;
        int receivedCount2;
        XmlDocument sampleDoc;
        XmlDocument receivedDoc1;
        XmlDocument receivedDoc2;

        [TestFixtureSetUp]
		public void TestFixtureSetup()
		{
            try
            {
                MessageQueue.Delete(".\\private$\\QueueNone");
                MessageQueue.Delete(".\\private$\\Queue1");
                MessageQueue.Delete(".\\private$\\Queue2");
                MessageQueue.Delete(".\\private$\\Queue3");
            }
            catch (MessageQueueException e) { Console.Write (e); }
            factory = new MessageGatewayFactoryMSMQ();
        }

        [SetUp]
        public void Setup()
        {
            receivedCount1 = 0;
            receivedCount2 = 0;
            receivedDoc1 = null;
            receivedDoc2 = null;
            string xml = "<foo>poop</foo>";
            sampleDoc = new XmlDocument();
            sampleDoc.LoadXml(xml);
        }

        [Test]
        public void testNoSubscribers()
        {
            IMessageSender sender = factory.GetSenderInstance("QueueNone");

            sender.Send(sampleDoc);
        }

        [Test]
        public void testLateSubscribersGetTheMessage()
        {
            IMessageReceiver receiver = factory.GetReceiverInstance("QueueNone");
            receiver.AddEventHandler(new OnMsgEvent(OnMessage1));
            receiver.Activate();
            Thread.Sleep(500); // this is asynchronous, so wait a little

            Assert.AreEqual(1, receivedCount1);
            Assert.AreEqual(sampleDoc.InnerXml, receivedDoc1.InnerXml);
        }

        [Test]
        public void testOneSubscriber()
        {
            IMessageSender sender = factory.GetSenderInstance("Queue1");
            IMessageReceiver receiver = factory.GetReceiverInstance("Queue1");

            receiver.AddEventHandler(new OnMsgEvent(OnMessage1));
            receiver.Activate();

            sender.Send(sampleDoc);
            Thread.Sleep(500); // this is asynchronous, so wait a little

            Assert.AreEqual(1, receivedCount1);
            Assert.AreEqual(sampleDoc.InnerXml, receivedDoc1.InnerXml);
        }

        [Test]
        public void testTwoSubscribers()
        {
            IMessageSender sender = factory.GetSenderInstance("Queue2");
            IMessageReceiver receiver = factory.GetReceiverInstance("Queue2");

            receiver.AddEventHandler(new OnMsgEvent(OnMessage1));
            receiver.AddEventHandler(new OnMsgEvent(OnMessage2));
            receiver.Activate();

            sender.Send(sampleDoc);
            Thread.Sleep(500); // this is asynchronous, so wait a little

            Assert.AreEqual(1, receivedCount1);
            Assert.AreEqual(sampleDoc.InnerXml, receivedDoc1.InnerXml);
            Assert.AreEqual(1, receivedCount2);
            Assert.AreEqual(sampleDoc.InnerXml, receivedDoc2.InnerXml);
        }

        [Test]
        public void testNoMessagesReceivedUntilBegin()
        {
            IMessageSender sender = factory.GetSenderInstance("Queue3");
            IMessageReceiver receiver = factory.GetReceiverInstance("Queue3");

            receiver.AddEventHandler(new OnMsgEvent(OnMessage1));
            sender.Send(sampleDoc);
            sender.Send(sampleDoc);
            Thread.Sleep(500); // this is asynchronous, so wait a little

            Assert.AreEqual(0, receivedCount1);

            receiver.Activate();
            Thread.Sleep(500); // this is asynchronous, so wait a little

            Assert.AreEqual(2, receivedCount1);
            Assert.AreEqual(sampleDoc.InnerXml, receivedDoc1.InnerXml);
        }

        public void OnMessage1(XmlDocument doc)
        {
            receivedCount1++;    
            receivedDoc1 = doc;
        }

        public void OnMessage2(XmlDocument doc)
        {
            receivedCount2++;
            receivedDoc2 = doc;
        }

	}
}
